home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The PC-SIG Library 10
/
The PC-Sig Library - Shareware for the IBM PC and Compatibles (PC-SIG)(Tenth Edition Disks 1-2804)(1991).iso
/
PC_SIGCD
/
02
/
8
/
DISK0285.ZIP
/
ASMBASIC.TXT
< prev
next >
Wrap
Text File
|
1984-07-11
|
8KB
|
240 lines
File: ASMBASIC.TXT On: CLUBware Software Diskette #1
Author: Stan Radzio
Copyright (C) 1984. RAYHAWK AUTOMATION, N W, INC.
ASMBASIC represents an improved approach for calling assembly
language routines from IBM PC BASIC. The major improvement is that
this approach allows the same source code to be used by both the
BASIC Interpreter and the BASIC Compiler. Hence, you can debug a
program in the more productive interpreter environment and migrate
them easily to the faster executing compiled environment.
The published approaches in the magazines make it very difficult to
use the same source to both programs. These approaches involve
storing routines within BASIC arrays or in high memory beyond the
reaches of the interpreter. ASMBASIC stores the assembly routines in
low memory below the Basic interpreter.
The required subroutines are not loaded with BLOAD or POKE; they are
already resident in memory when the Basic interpreter is invoked.
ASMBASIC is distributed already assembled and linked with eight
assembly language subroutines:
QPRINT - quickly print a string at the current location
ZPRINT - print a string using the color/attribute given
SCRLDN - scroll some portion of the screen down
SCRLUP - scroll some portion of the screen up
XREP - repeat some character along the x axis
YREP - repeat some character down the y axis
CLREOL - clear from the current position to the end of the line
CLREOS - clear from the current position to the end of the screen
The source to ASMBASIC is included on the CLUBware diskette so that
these subroutines may be replaced with ones of your own choosing or so
that you may add additional subroutines.
The technique is demonstrated in program SUBDEMO.BAS and works like
this:
1) Assemble your utility subroutines.
2) Enter the names of your assembly routines into the subroutine table
within ASMBASIC.
3) The first name in the table is subroutine 1.
The second name in the table is subroutine 2.
Print the table so you won't forget the ordering of names.
4) Assemble ASMBASIC and link it with your assembly language routines.
5) Execute ASMBASIC to make the code resident. You need only execute
ASMBASIC once after the system is booted. However, if you execute
it more than once, no harm will be done.
File: ASMBASIC.TXT Page 2
Review SUBDEMO.BAS. You will see a method which allows the Basic
program to determine if it is running compiled or interpreted.
(The interpreter uses 3 bytes for the string descriptor; the
compiler uses 4 bytes. Hence, the difference in the offsets of
successive elements of a string array is either 3 or 4.) If
SUBDEMO.BAS is running compiled, it will jump to step 11.
For the steps 6-10, assume you are still developing the code under
the interpreter.
6) Bring up the Basic interpreter. Load and run a program with code
equivalent to SUBDEMO.BAS. This will check for running under the
interpreter. Since it is, it will do the following:
7) Poke a two line subroutine into an array:
INT 67
RET
We call this subroutine SUBINIT. (Note that ASMBASIC services
interrupt 67.)
8) Call SUBINIT with an argument of 1 to learn the offset of
subroutine 1 (the first subroutine in the subroutine table). Call
SUBINIT with a 2 to learn the offset of subroutine 2, etc.
I% = 1 'We want the offset to the first routine
CALL SUBINIT(I%) 'SUBINIT will place the offset into I%
QPRINT = I% 'Copy the offset into variable QPRINT
I% = 2 'We want the offset to the second routine
CALL SUBINIT(I%) 'SUBINIT will place the offset into I%
SUB2 = I% 'Copy the offset into variable QPRINT
9) After processing all the names in the subroutine table, call
SUBINIT with an argument of 0 to learn the code segment where
ASMBASIC has stored your subroutines.
CODESEG% = 0 'To get the Code Segment, use 0 as input.
CALL SUBINIT(CODESEG%) 'SUBINIT will return code segment.
10) Use the Basic DEF SEG statement to make your assembly language
routines callable.
DEF SEG = CODESEG%
11) Call the subroutines wherever and whenever you want:
CALL QPRINT ( FLAG% , MYSTRING$ )
CALL SUB2( ARG1 , ARG2% , ARG3$ )
Since steps 6-10 are skipped during execution of the compiled
version, the above CALL statements are executed as we desire.
Under the interpreter, QPRINT and SUB2 are treated as VARIABLES.
File: ASMBASIC.TXT Page 3
Some General Comments
An obvious benefit to using ASMBASIC over storing assembly subroutines
in arrays is that the assembly code does not reduce the amount of
memory available for variables and string storage (assuming sufficient
physical memory in the machine).
Assembly language programmers will appreciate the ease with which
assembly routines can be debugged. Link your new subroutine into
ASMBASIC. Invoke ASMBASIC to make your routine resident. Bring up
the Basic interpreter under DOS Debug:
DEBUG BASICA.COM
You can find the subroutine table by looking down the interrupt vector
for INT 67h (used to invoke SUBINIT).
-D 00:19C L4
0000:019C 2C 00 10 06
The subroutine table is 2 bytes after the address in the interrupt
vector. In this example: 0610:002C + 2 = 0610:002E
Display the subroutine table.
-D 0610:002E L10
0610:002E 19 01
0610:0030 30 01 B0 02 F0 02 D0 04-30 03 70 02 F0 01
The eight subroutines in this example can be found at
0610:0119 QPRINT 1
0610:0130 SCRLDN 2
0610:02B0 SCRLUP 3
0610:02F0 XREP 4
0610:04D0 YREP 5
0610:0330 CLREOL 6
0610:0270 CLREOS 7
0610:01F0 ZPRINT 8
Start the interpreter and set breakpoints at the start of the
subroutines you wish to debug:
-G 610:119
ASMBASIC will not make itself resident more than once after the system
is booted. If you are modifying and assembling a new subroutine (and
relinking it into ASMBASIC) then you should comment out the:
JMP SHORT ALREADY_RESIDENT
instruction in ASMBASIC so that each execution of ASMBASIC will make
your latest copy of the subroutine available for debugging.
File: ASMBASIC.TXT Page 4
A subtle benefit of ASMBASIC is easy addressability for local data
segments. In contrast, assembly routines POKE'd or BLOAD'ed into
memory do not have relocation services performed for them. For
example, the following subroutine will work with ASMBASIC and will
fail if attempted with POKE.
LOCLSEG SEGMENT
my local data
LOCLSEG ENDS
CODE SEGMENT PARA PUBLIC 'CODE'
PUBLIC MYSUB
ASSUME CS:CODE,ES:LOCLSEG
MYSUB PROC FAR
MOV AX,SEG LOCLSEG
MOV ES,AX
rest of subroutine
MYSUB ENDP
CODE ENDS
END
The standard way of allowing routines called by BASIC to have their
own data areas has some undesirable aspects. First, the code must be
linked /HIGH. Then, it is loaded by the Debugger (who performs the
relocation needed), BSAVE'ed by the interpreter, then BLOAD'ed into
the exact same location by the interpreter when needed. There is an
incomplete description of this latter method in the back of the BASIC
manual. Note that the location occupied by such a BLOAD'ed routine is
the same memory location which will hold BASRUN.EXE if the BASIC code
is ever compiled and executed.
For a more reasonable approach, try ASMBASIC.